

import { ESize, EVector2, EVector3 } from "../../engine/Math";
import { astar } from "./AStar";

export type AStarMoveAbleFunc = (s: number, t: number, param?: any) => boolean;
/**
 * 45角地图
 */
export class MapAStar {

    //地图的像素长宽
    protected _mapContent: ESize = null;
    //单个格子的像素长宽
    protected _gridESize: ESize = null;

    protected _star: astar.AStar = new astar.AStar();

    protected _grid: astar.Grid = null;

    // protected _moveAbleFuncMap: Map<MapAstarType, AStarMoveAbleFunc> = new Map<MapAstarType, AStarMoveAbleFunc>();

    protected temp: EVector2 = new EVector2()
    protected tilePosDiv: EVector3 = new EVector3();
    protected _aStarMoveAbleFunc: AStarMoveAbleFunc = null;

    protected _param: any;

    setMoveAbleFunc(func: AStarMoveAbleFunc) {
        this._aStarMoveAbleFunc = func;
    }

    init(mapESize: ESize, mapContent: ESize, gridESize: ESize) {
        this._mapContent = mapContent;
        this._gridESize = gridESize;
        this._grid = new astar.Grid(mapESize.width, mapESize.height);
        this._grid.setMoveAbleFunc((x: number, y: number) => {
            if (this._aStarMoveAbleFunc) {
                return this._aStarMoveAbleFunc(x, y, this._param)
            }
        })
    }

    protected canMove(x: number, y: number) {
        let posId = this._grid.getTileIndexByXY(x, y)
    }


    findPath(param: any, startCoord: EVector2, endCoord: EVector2): { x: number, y: number }[] {
        this._param = param;
        this._grid.setStartNode(startCoord.x, startCoord.y);
        this._grid.setEndNode(endCoord.x, endCoord.y);
        this._star.findPath(this._grid);
        return this._star.path;
    }


    /**
     * 格子坐标转像素坐标
     * @param tileCoord 
     * @param out 
     * @returns 
     */
    coordToPosition(tileCoord: EVector2, out?: EVector3): EVector3 {
        let tileESize = this._gridESize;
        let mapESizeH = this._grid.numRows;
        let contentESize = this._mapContent;

        let startPosX = mapESizeH * (tileESize.width / 2);
        let startPosY = contentESize.height;
        this.tilePosDiv.x = (tileCoord.x - tileCoord.y) / 2;
        this.tilePosDiv.y = (-tileCoord.x - tileCoord.y) / 2;
        let x = this.tilePosDiv.x * tileESize.width + startPosX;
        let y = this.tilePosDiv.y * tileESize.height + startPosY - tileESize.height / 2;
        if (out) {
            out.set(x, y, 0);
        } else {
            out = new EVector3(x, y, 0);
        }
        return out;
    }

    /**
     * 像素坐标转格子坐标
     * @param position 
     */
    positionToCoord(position: EVector3, out?: EVector2): EVector2 {
        return this.positionToCoord2(position.x, position.y, out);
    }
    /**
      * 像素坐标转格子坐标
      * @param position 
      */
    positionToCoord2(x: number, y: number, out?: EVector2): EVector2 {
        let tileESize = this._gridESize;
        let mapESizeH = this._grid.numRows;
        let contentESize = this._mapContent;

        let startPosX = mapESizeH * (tileESize.width / 2);
        let startPosY = contentESize.height;

        this.tilePosDiv.x = (x - startPosX) / tileESize.width;
        this.tilePosDiv.y = (y - startPosY) / tileESize.height;
        let posX = Math.floor(this.tilePosDiv.x - this.tilePosDiv.y);
        let posY = Math.floor(-this.tilePosDiv.x - this.tilePosDiv.y);
        if (out) {
            out.set(posX, posY);
        } else {
            out = new EVector2(posX, posY);
        }
        return out;
    }


    /**
     * 格子坐标转格子编号
     * @param tileCoord 
     * @returns 
     */
    public coordToIndex(tileCoord: EVector3): number {
        let mapESizeW = this._grid.numCols;
        let index = tileCoord.y * mapESizeW + tileCoord.x;
        return index;
    }

    /**
     * 格子编号转格子坐标
     * @param index 
     * @param out 
     * @returns 
     */
    public indexToCoord(index: number, out?: EVector2): EVector2 {
        let mapESizeW = this._grid.numCols;
        let mapESizeH = this._grid.numRows;
        let x = Math.floor(index % mapESizeW);
        let y = Math.floor(index / mapESizeH);
        if (out) {
            out.x = x;
            out.y = y;
            return out;
        }
        out = new EVector2(x, y);
        return out;

    }

}